package vitaliy.bondar.diamondcave;

import java.util.Vector;

import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.text.Text;
import org.andengine.input.touch.TouchEvent;
import org.andengine.util.color.Color;

import vitaliy.bondar.diamondcave.SceneManager.SceneType;
import android.view.MotionEvent;

public class SelectorScene extends BaseScene implements IOnSceneTouchListener
{
    protected static int LEVELS = 21;
    protected static int LEVEL_COLUMNS_PER_SCREEN = 5;
    protected static int LEVEL_ROWS_PER_SCREEN = 3;
    protected static int LEVEL_PADDING = 50;
    protected static int TEXT_PADDING = 80;

    private Vector< LevelBox > m_boxes;
    private int m_pageCount;
    private Text m_bottomText;
    private int m_currentPage;

    private int m_maxLevelReached;
    private float m_touchX;
    private boolean m_isMoving;
    private float m_scrollOffset = 100;

    @Override
    public void createScene()
    {
        m_maxLevelReached = maxLevelReached();
        m_pageCount = LEVELS / (LEVEL_COLUMNS_PER_SCREEN * LEVEL_ROWS_PER_SCREEN);
        m_currentPage = -1;

        setBackground(new Background(Color.BLACK));

        m_boxes = new Vector< LevelBox >();
        m_boxes.setSize(LEVEL_COLUMNS_PER_SCREEN * LEVEL_ROWS_PER_SCREEN);

        m_bottomText = new Text(camera.getCenterX(), camera.getHeight() - TEXT_PADDING,
                resourcesManager.font, "01234567890/ ", vbom);
        m_bottomText.setText("");

        this.attachChild(m_bottomText);

        this.setOnSceneTouchListener(this);
        createBoxes();
        setCurrentLevel(m_maxLevelReached);
        m_isMoving = false;
    }

    @Override
    public void disposeScene()
    {
        activity.runOnUpdateThread(new Runnable()
        {
            @Override
            public void run()
            {
                setChildrenIgnoreUpdate(true);
                setIgnoreUpdate(true);
                detachChildren();
                ResourcesManager.getInstance().unloadSelectorResources();
            }
        });
    }

    @Override
    public void onBackKeyPressed()
    {
        SceneManager.getInstance().loadMenuScene(engine);
    }

    @Override
    public SceneType getSceneType()
    {
        return SceneType.SCENE_LEVEL_SELECTOR;
    }

    public void createBoxes()
    {
        int spaceX = ((int)camera.getWidth() - 2 * LEVEL_PADDING - LEVEL_COLUMNS_PER_SCREEN
                * LevelBox.getWidth())
                / (LEVEL_COLUMNS_PER_SCREEN - 1) + LevelBox.getWidth();

        int spaceY = ((int)camera.getHeight() - LEVEL_PADDING - TEXT_PADDING - LEVEL_ROWS_PER_SCREEN
                * LevelBox.getHeight())
                / (LEVEL_ROWS_PER_SCREEN - 1) + LevelBox.getHeight();

        int x = LEVEL_PADDING;
        int y = LEVEL_PADDING;

        for (int i = 0; i < LEVEL_ROWS_PER_SCREEN; ++i)
        {
            for (int j = 0; j < LEVEL_COLUMNS_PER_SCREEN; ++j)
            {
                LevelBox box = new LevelBox(x, y, vbom)
                {
                    @Override
                    public void onClick()
                    {
                        if (m_isMoving || !this.isOpened())
                        {
                            m_isMoving = false;
                            return;
                        }
                        loadLevel(this.levelNumber());
                    }
                };

                m_boxes.set((i * LEVEL_COLUMNS_PER_SCREEN + j), box);
                this.attachChild(box);

                x += spaceX;
            }
            x = LEVEL_PADDING;
            y += spaceY;
        }
    }

    public void setCurrentLevel(final int levelNumber)
    {
        setPage(levelNumber / (LEVEL_COLUMNS_PER_SCREEN * LEVEL_ROWS_PER_SCREEN));
    }
    
    private void setPage(final int number)
    {
        if (m_currentPage == number || number > m_pageCount) return;

        m_currentPage = number;
        m_bottomText.setText((number + 1) + " / " + (m_pageCount + 1));
        m_bottomText.setX(camera.getCenterX() - m_bottomText.getWidth() / 2);

        final int levelsPerPage = LEVEL_COLUMNS_PER_SCREEN * LEVEL_ROWS_PER_SCREEN;
        int currentNumber = number * levelsPerPage + 1;

        for (int i = 0; i < m_boxes.size(); ++i)
        {
            LevelBox box = m_boxes.elementAt(i);
            box.setOpened(currentNumber <= m_maxLevelReached);
            box.setLevelNumber(currentNumber);
            box.setVisible(currentNumber <= LEVELS);
            ++currentNumber;
        }
    }

    private void loadLevel(final int level)
    {
        SceneManager.getInstance().loadGameScene(engine, level);
    }

    private int maxLevelReached()
    {
        return prefrences.getInt("level", 1);
    }

    @Override
    public boolean onSceneTouchEvent(Scene scene, TouchEvent event)
    {
        if (event.getAction() == MotionEvent.ACTION_DOWN)
        {
            m_touchX = event.getMotionEvent().getX();
            m_isMoving = true;
            return true;
        }
        if (event.getAction() == MotionEvent.ACTION_UP)
        {
            float offset = event.getMotionEvent().getX() - m_touchX;
            m_isMoving = false;

            if (Math.abs(offset) < m_scrollOffset)
            {
                float x = event.getX();
                float y = event.getY();
                for (final LevelBox box : m_boxes)
                {
                    if (box.contains(x, y))
                    {
                        box.onClick();
                        return true;
                    }
                }
                return true;
            }
            return false;
        }
        else if (event.getAction() == MotionEvent.ACTION_MOVE)
        {
            float offset = event.getMotionEvent().getX() - m_touchX;

            if (offset < -m_scrollOffset)
            {
                if (m_currentPage == m_pageCount) return true;
                this.setPage(m_currentPage + 1);
                return true;
            }
            else if (offset > m_scrollOffset)
            {
                if (m_currentPage == 0) return true;
                this.setPage(m_currentPage - 1);
                return true;
            }
        }

        return false;
    }
}
